/*
 * Licensed to the Tai Ping Jin Ke
 *
 * Copyright (c) 2022 .
 * All rights reserved.
 * 项目名称：太平金科-基础组件封装层-SpringBoot组件封装-缺省实现
 * 版权说明：本软件属太平金融科技服务(上海)有限公司所有，在未获得太平金融科技服务(上海)有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.taipingframework.boot.web.exception.handler;

import cn.hutool.core.date.DatePattern;
// import com.taipingframework.utility.exception.ServiceException;
import com.taipingframework.boot.web.response.result.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
// import org.springframework.http.HttpStatus;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
// import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 业务逻辑层(微服务) - 全局异常处理类，捕获异常后 返回JSON格式报文。
 * <p>
 * 如果使用了 注解@ControllerAdvice，则需要搭配注解@ResponseBody才能返回JSON格式报文。
 * <p>
 * 在@ControllerAdvice中除了配置@InitBinder,还可以有@ExceptionHandler用于全局处理控制器里面的异常；
 * 另外，@ModelAttribute作用是绑定键值对到Model里，让全局的@RequestMapping都能获得在此处设置的键值对。
 */
@Slf4j
@RestControllerAdvice
public class ServiceExceptionHandler {

    /**
     * 应用到所有使用了@RequestMapping注解的方法，在其执行之前初始化数据绑定器
     */
    @InitBinder
    public void initWebBinder(WebDataBinder binder) {
        log.debug("开始初始化数据绑定器");
        // 把String类型的参数先trim再绑定
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
        // 把Date类型的参数先格式化再绑定
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN), false));
    }

    /**
     * 通过 @ModelAttribute 注解的方法 会在每个被 @RequestMapping 注解的方法 执行前被调用。
     * 将数据添加到模型对象中，用于视图页面展示时使用。
     * 把值绑定到Model中，使全局@RequestMapping可以获取到该值
     */
    @ModelAttribute
    public void addAttribute(Model model) {
        log.debug("开始绑定初始化模型对象");
        // model.addAttribute(ApplicationConstant.RESPONSE_IDENTITY, RequestIdentityHelper.getRequestId());
    }

    /*
     * 全局异常捕捉处理，返回JSON格式类型
     *
    @ExceptionHandler(value = {ServiceException.class}) // 指定拦截异常的类型，由业务逻辑层(微服务)异常类统一处理异常信息
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 自定义浏览器返回状态码
    public ApiResult<Serializable> jsonExceptionHandler(ServiceException exception) {
        StringJoiner joiner = new StringJoiner("");
        ApiResult<Serializable> result = ApiHelper.buildResult(exception.getMessage(), joiner);
        log.error(joiner.toString(), exception);
        // 将异常响应结果返回
        return result;
    }*/

    /**
     * 全局异常捕捉处理，返回JSON格式类型
     */
    @ExceptionHandler
    public ApiResult<Serializable> jsonExceptionHandler(Exception exception) {
        return ExceptionConverter.convert(exception);
    }
}
